﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using Microsoft.Web.Administration;
using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.Diagnostics;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace FastMvcWebRole
{
    public class WebRole : RoleEntryPoint
    {
        public override bool OnStart()
        {
            SetupWad();

            //Várunk egy kicsit, mert a DiagnosticMonitor aszinkron indul el...
            Thread.Sleep(3000);

            SetupIIS("Web", "FastMvcWebRoleWarmUp", "FastMvcWebRole.Helpers.WarmUp, FastMvcWebRole");

            return base.OnStart();
        }

        /// <summary>
        /// A Windows Azure Diagnosics inicializálása
        /// </summary>
        private void SetupWad()
        {
            var config = DiagnosticMonitor.GetDefaultInitialConfiguration();
            config.Logs.BufferQuotaInMB = 100;
            config.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1D);
            config.Logs.ScheduledTransferLogLevelFilter = LogLevel.Verbose;
            DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);
        }


        /// <summary>
        /// Az site és az application pool beállításainak módosítása az IIS konfigurációkban
        /// </summary>
        /// <param name="siteName">A paraméter ServiceDefinition.csdef fájl Site name-re utal</param>
        /// <param name="keyName">A serviceAutoStart elem egyedi kulcsa (IIS szinten)</param>
        /// <param name="methodReference">A Warm Up metódus referenciája "Namespace.Metodus, Assembly" formátumban</param>
        private void SetupIIS(string siteName, string keyName, string methodReference)
        {
            using (var serverManager = new ServerManager())
            {
                var siteRealName = string.Format("{0}_{1}", RoleEnvironment.CurrentRoleInstance.Id, siteName);

                var site = serverManager.Sites[siteRealName];
                if (site == null)
                    throw new Exception(String.Format("Site not found: {0}", siteRealName));

                var siteApplication = site.Applications.FirstOrDefault();
                if (siteApplication == null)
                    throw new Exception(String.Format("Site Application (first) not found:{0}", siteRealName));

                var appPoolName = siteApplication.ApplicationPoolName;
                var appPool = serverManager.ApplicationPools[appPoolName];

                //Egy óra tétlenség után legyen recycle
                appPool.ProcessModel.IdleTimeout = TimeSpan.FromMinutes(60);

                //Periodikusan is legyen recycle
                appPool.Recycling.PeriodicRestart.Time = TimeSpan.FromHours(29);

                //Tegyük az Application Pool-t Always Running módba
                appPool["startMode"] = "AlwaysRunning";

                //Állítsuk be a site-on is az AutoStart szolgáltatás engedélyezését
                siteApplication["serviceAutoStartEnabled"] = true;

                //Adjuk meg az AutoStart providerünk kulcsát
                siteApplication["serviceAutoStartProvider"] = keyName;

                //Adjunk hozzá egy elemet (saját providerünk) az serviceAutoStartProviders kollekcióhoz
                var config = serverManager.GetApplicationHostConfiguration();
                var serviceAutoStartProvidersSection = config.GetSection("system.applicationHost/serviceAutoStartProviders");
                var serviceAutoStartProvidersCollection = serviceAutoStartProvidersSection.GetCollection();

                var serviceAutoStartProviderElement =
                    serviceAutoStartProvidersCollection.SingleOrDefault(f => f.ElementTagName == "add" && (string)f.Attributes["name"].Value == keyName);

                if (serviceAutoStartProviderElement != null)
                    serviceAutoStartProvidersCollection.Remove(serviceAutoStartProviderElement);

                serviceAutoStartProviderElement = serviceAutoStartProvidersCollection.CreateElement("add");
                serviceAutoStartProviderElement["name"] = keyName;
                serviceAutoStartProviderElement["type"] = methodReference;
                serviceAutoStartProvidersCollection.Add(serviceAutoStartProviderElement);

                serverManager.CommitChanges();
            }
        }
    }
}
